import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV

# 数据收集阶段
data = pd.read_excel("F:\\作业2\\机器学习\\2024020121195 周先真 机器学习\\数据.xlsx")


# 将数据转换成DataFrame格式
df = pd.DataFrame(data)

# 数据清洗阶段
label_encoder = LabelEncoder()
df['性别'] = label_encoder.fit_transform(df['性别'])  # 将性别转为0和1，便于机器学习模型处理

# 对“喜欢的事情”列进行独热编码（One-Hot Encoding），将每种喜好转换为一个新的二进制特征
# one_hot_encoder = pd.get_dummies(df['喜欢的事情'], prefix='喜欢的事情')
# df = pd.concat([df, one_hot_encoder], axis=1)  # 将独热编码结果与原数据合并
# df = df.drop('喜欢的事情', axis=1)  # 删除原始的'喜欢的事情'列
print(df.columns)

# 特征工程阶段
# 1. 特征缩放：标准化年龄特征，使得其均值为0，方差为1，避免模型训练时不同特征尺度的影响。
scaler = StandardScaler()
df['年龄'] = scaler.fit_transform(df[['年龄']])

# 数据划分阶段
# 将数据集分为训练集和测试集。我们选择70%的数据作为训练集，30%作为测试集。
X = df.drop('喜欢的事情', axis=1)  # 特征：去除标签列，剩余的列作为特征
y = df['喜欢的事情']  # 标签：性别列作为目标标签

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

# 模型训练阶段
# 选择随机森林分类器作为模型进行训练。随机森林是一种集成学习方法，通常具有较强的泛化能力。
# 模型训练阶段（优化前）
model = RandomForestClassifier()
model.fit(X_train, y_train)  # 使用训练集进行训练

# 模型预测阶段（优化前）
y_pred_before_tuning = model.predict(X_test)

# 模型评估阶段（优化前）
accuracy_before_tuning = accuracy_score(y_test, y_pred_before_tuning)
print(f'优化前的模型准确率: {accuracy_before_tuning * 100:.2f}%')

# 超参数调优阶段
# 使用GridSearchCV来进行超参数的调优，选择多个候选超参数，通过交叉验证（cv=5）来选择最佳参数。
param_grid = {
    'n_estimators': [50, 100, 200],  # 树的数量
    'max_depth': [None, 10, 20],  # 树的最大深度
    'min_samples_split': [2, 5, 10]  # 内部节点再划分所需最小样本数
}

grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=3, n_jobs=-1)
grid_search.fit(X_train, y_train)  # 使用训练集进行调优

# 获取最佳超参数
print("最佳超参数:", grid_search.best_params_)

# 使用最佳参数重新训练模型
best_model = grid_search.best_estimator_

# 模型预测阶段
# 使用训练好的最佳模型进行测试集的预测，并计算模型的准确率。
y_pred = best_model.predict(X_test)

# 模型评估阶段
# 计算预测结果的准确率，评估模型在测试集上的表现。
accuracy = accuracy_score(y_test, y_pred)
print(f'优化后的模型准确率: {accuracy * 100:.2f}%')

# 使用交叉验证评估模型的泛化能力
# 通过交叉验证（cv=5），计算模型在整个数据集上的表现，以验证模型的稳定性。
cv_scores = cross_val_score(best_model, X, y, cv=5)
print(f'交叉验证的准确率: {cv_scores.mean() * 100:.2f}%')
